package config

import (
	"zlash/component/fakeip"
	"zlash/component/trie"
	C "zlash/constant"
	"zlash/dns"
	"zlash/log"
	T "zlash/tunnel"
)

type General struct {
	LegacyInbound
	Controller
	Authentication []string     `json:"authentication"`
	Mode           T.TunnelMode `json:"mode"`
	LogLevel       log.LogLevel `json:"log-level"`
	IPv6           bool         `json:"ipv6"`
	Interface      string       `json:"-"`
	RoutingMark    int          `json:"-"`
}

type Controller struct {
	ExternalController string `json:"-"`
	ExternalUI         string `json:"-"`
	Secret             string `json:"-"`
}

type LegacyInbound struct {
	Port        int    `json:"port"`
	SocksPort   int    `json:"socks-port"`
	RedirPort   int    `json:"redir-port"`
	TProxyPort  int    `json:"tproxy-port"`
	MixedPort   int    `json:"mixed-port"`
	AllowLan    bool   `json:"allow-lan"`
	BindAddress string `json:"bind-address"`
}

type DNS struct {
	Enable            bool
	IPv6              bool
	NameServer        []dns.NameServer
	Fallback          []dns.NameServer
	FallbackFilter    FallbackFilter
	Listen            string
	EnhancedMode      C.DNSMode
	DefaultNameserver []dns.NameServer
	FakeIPRange       *fakeip.Pool
}

type FallbackFilter struct {
}

type Profile struct {
	StoreSelected bool
	StoreFakeIP   bool
}

type Experimental struct {
	UDPFallbackMatch bool `yaml:"udp-fallback-match"`
}
type Config struct {
	General      *General
	DNS          *DNS
	Experimental *Experimental
	Hosts        *trie.DomainTrie
}

type RawDNS struct {
	Enable            bool
	IPv6              *bool
	UseHosts          bool
	NameServer        []string
	Fallback          []string
	FallbackFilter    RawFallbackFilter
	Listen            string
	EnhancedMode      C.DNSMode
	FakeIPRange       string
	FakeIPFilter      []string
	DefaultNameserver []string
	NameServerPolicy  map[string]string
	SearchDomains     []string
}

type RawFallbackFilter struct {
	GeoIP     bool
	GeoIPCode string
	IPCIDR    []string
	Domain    []string
}

type tunnel struct {
	Network []string
	Address string
	Target  string
	Proxy   string
}

type Tunnel tunnel

type RawConfig struct {
	Port               int `yaml:"port"`
	SocksPort          int
	RedirPort          int
	TProxyPort         int
	MixedPort          int
	Authentication     []string
	AllowLan           bool
	BindAddress        string
	Mode               T.TunnelMode
	LogLevel           log.LogLevel
	IPv6               bool
	ExternalController string
	ExternalUI         string
	Secret             string
	Interface          string
	RoutingMark        int
	Tunnels            []Tunnel

	ProxyProvider map[string]map[string]any
	Hosts         map[string]string
	Inbounds      []C.Inbound
	DNS           RawDNS
	Experimental  Experimental
	Profile       Profile
	Proxy         []map[string]any
	ProxyGroup    []map[string]any
	Rule          []string
}

func Parse(buf []byte) (*Config, error) {
	rawCfg, err := UnmarshalRawConfig(buf)
	if err != nil {
		return nil, err
	}
	return ParseRawConfig(rawCfg)
}

func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
	rawCfg := &RawConfig{
		AllowLan:       false,
		BindAddress:    "*",
		Mode:           T.Rule,
		Authentication: []string{},
		LogLevel:       log.INFO,
		Hosts:          map[string]string{},
		Rule:           []string{},
		Proxy:          []map[string]any{},
		ProxyGroup:     []map[string]any{},
		DNS:            RawDNS{},
		Profile:        Profile{},
	}
	return rawCfg, nil
}

func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {

}
